import os
import sys
import importlib
import scipy.ndimage as snd
os.chdir("../..")
directory_path = os.path.abspath(os.path.join("src"))
if directory_path not in sys.path:
sys.path.append(directory_path)
import EyeTraumaAnalysis
print(directory_path)
C:\Users\ethan\PycharmProjects\EyeTraumaAnalysis\src
importlib.reload(EyeTraumaAnalysis);
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
import matplotlib as mpl
import cv2
# images = ["10030.jpg", "10031.jpg", "10032.jpg", "10033.jpg", "10034.jpg", "10035.jpg", "10036.jpg", "10037.jpg", "10038.jpg", "10039.jpg", "10040.jpg", "10041.jpg", "10042.jpg"]
images = os.listdir('./data/01_raw/Ergonautus/Full Dataset/')
def get_spatial_metrics(mask):
# scipy can perform the mean (center of mass), but not the standard deviation
# spatial_means = snd.center_of_mass(mask)
x = np.linspace(0, 1, mask.shape[1])
y = np.linspace(0, 1, mask.shape[0])
xgrid, ygrid = np.meshgrid(x, y)
grids = {"x": xgrid, "y":ygrid}
to_return = {"x":{}, "y":{}}
for ind, grid in grids.items():
to_return[ind]["mean"] = np.mean(grids[ind], where=mask.astype(bool))
to_return[ind]["sd"] = np.std(grids[ind], where=mask.astype(bool))
return to_return
### Create K means clusters and masks
image = EyeTraumaAnalysis.Image("data/01_raw/14436.png")
img_bgr = image.img
img_hsv = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2HSV)
Z_hsv = img_hsv.reshape((-1,3))
# convert to np.float32
Z_hsv = np.float32(Z_hsv)
# define criteria, number of clusters(K) and apply kmeans()
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
K = 10
ret,label,centers=cv2.kmeans(Z_hsv,K,None,criteria,10,cv2.KMEANS_RANDOM_CENTERS)
# Now convert back into uint8, and make original image
centers = np.uint8(centers)
res_hsv = centers[label.flatten()]
res_hsv2 = res_hsv.reshape(img_hsv.shape)
res_bgr = cv2.cvtColor(res_hsv2, cv2.COLOR_HSV2BGR)
# res2 = cv2.cvtColor(res2, cv2.COLOR_RGB2GRAY)
# sort centers by HSV "value" - aka sort by grayscale
centers_sorted = centers[centers[:, 2].argsort()]
kmeans_thresholds = []
for ind in range(K):
kmeans_thresholds.append(cv2.inRange(res_hsv2,centers_sorted[ind],centers_sorted[ind]))
summed_image = np.zeros(kmeans_thresholds[0].shape)
for ind in range(K):
summed_image += int(ind/K*255) * kmeans_thresholds[ind]
centers_indices = centers_sorted.argsort(axis=0) # sorts each column separately
### Clustered View ### <-- for individual image use
fig, axs = plt.subplots(2, 2, figsize=(12,6))
im0=axs.flat[0].imshow(img_bgr)
im1=axs.flat[1].imshow(res_bgr)
im2=axs.flat[2].imshow(summed_image, cmap="gray")
im3=axs.flat[3].imshow(summed_image, cmap="terrain")
plt.colorbar(im3,ax=axs.flat[3], shrink=0.8)
<matplotlib.colorbar.Colorbar at 0x1f5e26dee48>
get_spatial_metrics(kmeans_thresholds[0])
{'x': {'mean': 0.5017151478843548, 'sd': 0.0847618072972454},
'y': {'mean': 0.48749778466138083, 'sd': 0.08289419964726637}}
array([4, 7, 0])
### Per Cluster Masking ### <-- for individual image use
def draw_cluster_masking(img):
row_ct = int(np.sqrt(K))
col_ct = int(np.ceil(K/row_ct))
fig, axs = plt.subplots(row_ct, col_ct, figsize=(12,6), sharex=True, sharey=True)
for ind in range(row_ct*col_ct):
if ind < K:
#target1 = cv2.bitwise_and(image.img,image.img, mask=~kmeans_thresholds[ind])
target1 = img.copy()
target1[kmeans_thresholds[ind].astype(bool)] = [127,255,127,255]
axs.flat[ind].imshow(target1)
spatial_metrics = get_spatial_metrics(kmeans_thresholds[ind])
hsv_rank = centers_indices[ind]
hsv_center = centers_sorted[ind]
# Draw left title
axs.flat[ind].set_title(
"HSV \n"+
f"#{hsv_rank[0]+1}, #{hsv_rank[1]+1}, #{hsv_rank[2]+1}" + "\n" +
f"({hsv_center[0]}, {hsv_center[1]}, {hsv_center[2]})",
fontsize=8, loc="left"
)
# Draw right title
axs.flat[ind].set_title(
f"Location:" + "\n"+
f"({spatial_metrics['x']['mean']*100:.1f}, {spatial_metrics['y']['mean']:.1%})" + "\n" +
f"({spatial_metrics['x']['sd']*100:.1f}, {spatial_metrics['y']['sd']:.1%})",
fontsize=8, loc="right", fontfamily="monospace",
)
# axs.flat[ind].set_title(
# f"HSV center: [{centers_sorted[ind,0]},{centers_sorted[ind,1]},{centers_sorted[ind,2]}]" )
#axs.flat[ind].imshow(kmeans_thresholds[ind], cmap="gray")
else:
# remove axes for empty cells
axs.flat[ind].axis("off")
draw_cluster_masking(image.img)
draw_cluster_masking(image.img)
target1[kmeans_thresholds[ind].astype(bool)]
array([[ 12, 12, 14, 255],
[ 11, 11, 13, 255],
[ 11, 11, 13, 255],
[ 11, 11, 11, 255],
[ 10, 10, 10, 255],
[ 10, 10, 10, 255],
[ 12, 12, 14, 255],
[ 13, 13, 15, 255],
[ 12, 12, 14, 255],
[ 12, 12, 14, 255],
[ 13, 13, 15, 255],
[ 11, 11, 13, 255],
[ 13, 13, 15, 255],
[ 12, 13, 17, 255],
[ 10, 11, 13, 255],
[ 12, 12, 14, 255],
[ 13, 13, 15, 255],
[ 12, 12, 14, 255],
[ 12, 12, 14, 255],
[ 12, 12, 14, 255],
[ 10, 10, 12, 255],
[ 12, 13, 17, 255],
[ 13, 14, 19, 255],
[ 11, 12, 16, 255],
[ 11, 12, 16, 255],
[ 11, 12, 16, 255],
[ 11, 11, 13, 255],
[ 11, 11, 13, 255],
[ 11, 11, 13, 255],
[ 9, 9, 11, 255],
[ 46, 46, 56, 255],
[ 9, 10, 15, 255],
[ 10, 11, 16, 255],
[ 9, 10, 15, 255],
[ 10, 11, 15, 255],
[ 11, 12, 16, 255],
[ 11, 11, 13, 255],
[ 11, 11, 13, 255],
[ 12, 12, 14, 255],
[ 11, 11, 13, 255],
[ 40, 40, 50, 255],
[ 8, 8, 16, 255],
[ 9, 10, 15, 255],
[ 38, 38, 48, 255],
[ 12, 12, 20, 255],
[ 12, 13, 18, 255],
[ 39, 39, 49, 255],
[ 38, 38, 48, 255],
[ 32, 32, 42, 255],
[ 26, 26, 36, 255],
[ 48, 48, 58, 255],
[ 22, 22, 32, 255],
[ 41, 41, 51, 255],
[ 15, 16, 21, 255],
[ 14, 15, 20, 255],
[ 14, 15, 20, 255],
[ 16, 16, 18, 255],
[ 15, 15, 17, 255],
[ 12, 13, 17, 255],
[ 10, 11, 15, 255],
[ 12, 13, 17, 255],
[ 13, 13, 21, 255],
[ 15, 15, 23, 255],
[ 22, 22, 32, 255],
[ 39, 39, 49, 255],
[ 19, 20, 25, 255],
[ 18, 19, 24, 255],
[ 14, 15, 20, 255],
[ 14, 15, 20, 255],
[ 15, 15, 17, 255],
[ 15, 15, 17, 255],
[ 14, 15, 19, 255],
[ 11, 12, 16, 255],
[ 8, 12, 15, 255],
[ 11, 15, 18, 255],
[ 11, 12, 17, 255],
[ 13, 13, 21, 255],
[ 15, 15, 23, 255],
[ 22, 22, 30, 255],
[ 38, 38, 48, 255],
[ 16, 16, 24, 255],
[ 15, 18, 25, 255],
[ 16, 16, 24, 255],
[ 14, 15, 20, 255],
[ 15, 15, 17, 255],
[ 12, 13, 15, 255],
[ 9, 10, 12, 255],
[ 9, 13, 16, 255],
[ 13, 17, 20, 255],
[ 15, 16, 21, 255],
[ 12, 13, 18, 255],
[ 11, 12, 17, 255],
[ 11, 12, 17, 255],
[ 16, 17, 22, 255],
[ 16, 16, 24, 255],
[ 16, 19, 26, 255],
[ 18, 18, 26, 255],
[ 16, 16, 24, 255],
[ 15, 15, 17, 255],
[ 14, 14, 16, 255],
[ 11, 12, 14, 255],
[ 10, 14, 17, 255],
[ 13, 17, 20, 255],
[ 16, 17, 22, 255],
[ 13, 14, 19, 255],
[ 12, 13, 18, 255],
[ 11, 12, 17, 255],
[ 17, 18, 23, 255],
[ 16, 16, 24, 255],
[ 17, 20, 27, 255],
[ 19, 19, 27, 255],
[ 17, 17, 25, 255],
[ 12, 13, 17, 255],
[ 10, 14, 17, 255],
[ 12, 16, 19, 255],
[ 16, 17, 22, 255],
[ 13, 14, 19, 255],
[ 12, 13, 18, 255],
[ 10, 11, 16, 255],
[ 16, 17, 22, 255],
[ 17, 20, 27, 255],
[ 20, 20, 28, 255],
[ 18, 18, 26, 255],
[ 13, 14, 18, 255],
[ 13, 14, 18, 255],
[ 11, 15, 18, 255],
[ 14, 15, 20, 255],
[ 12, 13, 18, 255],
[ 12, 13, 18, 255],
[ 10, 11, 16, 255],
[ 16, 17, 22, 255],
[ 16, 19, 24, 255],
[ 17, 20, 27, 255],
[ 19, 19, 27, 255],
[ 14, 15, 19, 255],
[ 13, 14, 18, 255],
[ 13, 14, 18, 255],
[ 13, 14, 19, 255],
[ 12, 13, 18, 255],
[ 12, 13, 18, 255],
[ 10, 11, 16, 255],
[ 17, 17, 19, 255],
[ 17, 18, 22, 255],
[ 16, 19, 24, 255],
[ 17, 20, 27, 255],
[ 19, 19, 27, 255],
[ 13, 14, 18, 255],
[ 12, 13, 17, 255],
[ 13, 14, 19, 255],
[ 12, 13, 18, 255],
[ 13, 14, 19, 255],
[ 11, 12, 17, 255],
[ 18, 19, 24, 255],
[ 18, 18, 26, 255],
[ 20, 20, 28, 255],
[ 14, 15, 19, 255],
[ 13, 14, 18, 255],
[ 14, 15, 20, 255],
[ 12, 13, 18, 255],
[ 14, 15, 20, 255],
[ 11, 12, 17, 255],
[ 21, 21, 23, 255],
[ 18, 19, 23, 255],
[ 19, 20, 25, 255],
[ 21, 21, 29, 255],
[ 15, 16, 20, 255],
[ 13, 14, 18, 255],
[ 13, 14, 19, 255],
[ 12, 13, 18, 255],
[ 14, 15, 20, 255],
[ 12, 13, 18, 255],
[ 19, 20, 25, 255],
[ 20, 21, 26, 255],
[ 17, 18, 23, 255],
[ 15, 16, 21, 255],
[ 13, 14, 19, 255],
[ 13, 14, 19, 255],
[ 14, 15, 20, 255],
[ 14, 15, 20, 255],
[ 20, 21, 26, 255],
[ 17, 18, 23, 255],
[ 16, 17, 22, 255],
[ 14, 15, 20, 255],
[ 14, 15, 20, 255],
[ 14, 15, 20, 255],
[ 15, 16, 21, 255],
[ 18, 19, 24, 255],
[ 17, 18, 23, 255],
[ 17, 18, 23, 255],
[ 17, 18, 23, 255],
[ 17, 18, 23, 255],
[ 18, 19, 24, 255],
[ 16, 17, 22, 255],
[ 15, 16, 21, 255],
[ 16, 17, 22, 255],
[ 17, 18, 23, 255],
[ 16, 17, 22, 255],
[ 12, 15, 20, 255],
[ 13, 16, 21, 255],
[ 17, 17, 25, 255],
[ 16, 16, 24, 255],
[ 13, 16, 23, 255],
[ 14, 17, 24, 255],
[ 16, 16, 24, 255],
[ 15, 15, 23, 255],
[ 17, 17, 25, 255],
[ 17, 17, 25, 255],
[ 14, 14, 22, 255],
[ 14, 14, 22, 255],
[ 17, 17, 25, 255],
[ 16, 16, 24, 255]], dtype=uint8)
image.img.shape
(240, 416, 4)
kmeans_thresholds[0].dtype
dtype('uint8')
xgrid
array([0. , 0. , 0. , ..., 0.61445783, 0.61445783,
0.61445783])
type(xgrid)
numpy.ndarray
### Running Code on Several Images ###
K = 10
# save_directory = "C:\\Users\\ethan\\PycharmProjects\\EyeTraumaAnalysis\\data\\kmeans_clustering_applied" # data/kmeans_clustering_applied; hard coded for PC
# NOTE: While this isn't a preferable implementation, the previous code, which was flexible per system, ran into PermissionError [Errno 13]
for image_sample in images:
# image = EyeTraumaAnalysis.Image(f"data/01_raw/{image_sample}")
image = EyeTraumaAnalysis.Image(f"data/01_raw/Ergonautus/Full Dataset/{image_sample}")
## Clustered View
img_bgr = image.img
img_hsv = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2HSV)
Z_hsv = img_hsv.reshape((-1,3))
Z_hsv = np.float32(Z_hsv)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
ret,label,centers=cv2.kmeans(Z_hsv,K,None,criteria,10,cv2.KMEANS_RANDOM_CENTERS)
centers = np.uint8(centers)
res_hsv = centers[label.flatten()]
res_hsv2 = res_hsv.reshape(img_hsv.shape)
res_bgr = cv2.cvtColor(res_hsv2, cv2.COLOR_HSV2BGR)
centers_sorted = centers[centers[:, 2].argsort()]
kmeans_thresholds = []
for ind in range(K):
kmeans_thresholds.append(cv2.inRange(res_hsv2,centers_sorted[ind],centers_sorted[ind]))
summed_image = np.zeros(kmeans_thresholds[0].shape)
for ind in range(K):
summed_image += int(ind/K*255) * kmeans_thresholds[ind]
fig, axs = plt.subplots(2, 2, figsize=(12,6))
im0=axs.flat[0].imshow(img_bgr)
im1=axs.flat[1].imshow(res_bgr)
im2=axs.flat[2].imshow(summed_image, cmap="gray")
im3=axs.flat[3].imshow(summed_image, cmap="terrain")
plt.colorbar(im3,ax=axs.flat[3], shrink=0.8)
save_directory = f"{directory_path}".replace("src", "data")
# plt.savefig(f"{save_directory}\\kmeans_clustering_applied\\K-{K}\\clustered_view\\{image_sample.split('.PNG')[0]}.png",
# format='png')
plt.savefig(f"{save_directory}\\kmeans_clustering_applied\\ergonautus-10k\\clustered_view\\{image_sample.split('.PNG')[0]}.png",
format='png')
## Per Cluster Masking
row_ct = int(np.sqrt(K))
col_ct = int(np.ceil(K/row_ct))
fig, axs = plt.subplots(row_ct, col_ct, figsize=(12,6), sharex=True, sharey=True)
for ind in range(row_ct*col_ct):
if ind < K:
#target1 = cv2.bitwise_and(image.img,image.img, mask=~kmeans_thresholds[ind])
target1 = image.img.copy()
target1[kmeans_thresholds[ind].astype(bool)] = [127,255,127,255]
axs.flat[ind].imshow(target1)
spatial_metrics = get_spatial_metrics(kmeans_thresholds[ind])
hsv_rank = centers_indices[ind]
hsv_center = centers_sorted[ind]
# Draw left title
axs.flat[ind].set_title(
"HSV \n"+
f"#{hsv_rank[0]+1}, #{hsv_rank[1]+1}, #{hsv_rank[2]+1}" + "\n" +
f"({hsv_center[0]}, {hsv_center[1]}, {hsv_center[2]})",
fontsize=8, loc="left"
)
# Draw right title
axs.flat[ind].set_title(
f"Location:" + "\n"+
f"({spatial_metrics['x']['mean']*100:.1f}, {spatial_metrics['y']['mean']:.1%})" + "\n" +
f"({spatial_metrics['x']['sd']*100:.1f}, {spatial_metrics['y']['sd']:.1%})",
fontsize=8, loc="right", fontfamily="monospace",
)
# axs.flat[ind].set_title(
# f"HSV center: [{centers_sorted[ind,0]},{centers_sorted[ind,1]},{centers_sorted[ind,2]}]" )
#axs.flat[ind].imshow(kmeans_thresholds[ind], cmap="gray")
else:
# remove axes for empty cells
axs.flat[ind].axis("off")
plt.savefig(f"{save_directory}\\kmeans_clustering_applied\\ergonautus-10k\\per_cluster_mask\\{image_sample.split('.PNG')[0]}.png", format='png')
# row_ct = int(np.sqrt(K))
# col_ct = int(np.ceil(K/row_ct))
# fig, axs = plt.subplots(row_ct, col_ct, figsize=(12,6), sharex=True, sharey=True)
# for ind in range(row_ct*col_ct):
# if ind < K:
# target1 = cv2.bitwise_and(image.img,image.img, mask=~kmeans_thresholds[ind])
# axs.flat[ind].imshow(target1)
# axs.flat[ind].set_title(
# f"Mean: {round(snd.mean(target1), 3)}\nStd: {round(snd.standard_deviation(target1), 3)}"
# )
# # axs.flat[ind].set_title(
# # f"HSV center: [{centers_sorted[ind,0]},{centers_sorted[ind,1]},{centers_sorted[ind,2]}]" )
# #axs.flat[ind].imshow(kmeans_thresholds[ind], cmap="gray")
# else:
# # remove axes for empty cells
# axs.flat[ind].axis("off")
# # plt.savefig(f"{save_directory}\\kmeans_clustering_applied\\K-{K}\\per_cluster_mask\\{image_sample.split('.jpg')[0]}.png", format='png')
# plt.savefig(f"{save_directory}\\kmeans_clustering_applied\\ergonautus-10k\\per_cluster_mask\\{image_sample.split('.PNG')[0]}.png", format='png')
# close to prevent overconsumption of memory
plt.close()
c:\users\ethan\pycharmprojects\eyetraumaanalysis\venv\lib\site-packages\ipykernel_launcher.py:44: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`). c:\users\ethan\pycharmprojects\eyetraumaanalysis\venv\lib\site-packages\ipykernel_launcher.py:29: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`).